package cn.lg.soar.common.util.desensitization;

import cn.lg.soar.common.util.reflect.ReflectUtil;
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;

import java.io.IOException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * 字符串脱敏注解
 * @author luguoxiang
 * @date 2022/2/19
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
@Target({ ElementType.FIELD, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = Desensitization.Serializer.class)
public @interface Desensitization {

    /**
     * 脱敏处理器
     * @return
     */
    Class<? extends DesensitizationHandler> value() default General.class;

    /**
     * 前缀保留长度
     * @return
     */
    int preLen() default 1;

    /**
     * 后缀保留长度
     * @return
     */
    int sufLen() default 1;

    /**
     * 脱敏符合
     * @return
     */
    String replacement() default  "**";

    /**
     * 序列化
     * @author luguoxiang
     * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
     */
    class Serializer extends JsonSerializer<Object> implements ContextualSerializer {
        private DesensitizationHandler handler;
        public Serializer() {}
        public Serializer(Desensitization annotation) {
            Class<? extends DesensitizationHandler> aClass = annotation.value();
            try {
                Constructor<? extends DesensitizationHandler> constructor = aClass.getConstructor(Desensitization.class);
                this.handler = constructor.newInstance(annotation);
            } catch (NoSuchMethodException e) {
                this.handler = ReflectUtil.newInstance(annotation.value());
            } catch (InvocationTargetException | InstantiationException | IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
        @Override
        public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            gen.writeString(handler.handle(value.toString()));
        }
        @Override
        public JsonSerializer<?> createContextual(final SerializerProvider serializerProvider,
                                                  final BeanProperty beanProperty) throws JsonMappingException {
            if (beanProperty != null) {
                Desensitization annotation = beanProperty.getAnnotation(Desensitization.class);
                if (annotation == null) {
                    annotation = beanProperty.getContextAnnotation(Desensitization.class);
                }
                if (annotation != null) {
                    return new Desensitization.Serializer(annotation);
                }
                return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
            }
            return serializerProvider.findNullValueSerializer(null);
        }

    }


    /**
     * 通用
     */
    class General implements DesensitizationHandler {
        private final int preLen;
        private final int sufLen;
        private final String replacement;
        public General(Desensitization annotation) {
            preLen = annotation.preLen();
            sufLen = annotation.sufLen();
            replacement = annotation.replacement();
        }
        @Override
        public String handle(String original) {
            return DesensitizationUtil.string(original, preLen, sufLen, replacement);
        }
    }

    /**
     * 手机号码脱敏
     */
    class Phone implements DesensitizationHandler {
        @Override
        public String handle(String original) {
            return DesensitizationUtil.phone(original);
        }
    }

    /**
     * 邮箱脱敏
     */
    class Email implements DesensitizationHandler {
        @Override
        public String handle(String original) {
            return DesensitizationUtil.email(original);
        }
    }

    /**
     * 身份证号码脱敏
     */
    class IdCard implements DesensitizationHandler {
        @Override
        public String handle(String original) {
            return DesensitizationUtil.idCard(original);
        }
    }

    /**
     * 银行卡脱敏
     */
    class Bankcard implements DesensitizationHandler {
        @Override
        public String handle(String original) {
            return DesensitizationUtil.bankcard(original);
        }
    }

    /**
     * 姓名脱敏
     */
    class RealName implements DesensitizationHandler {
        @Override
        public String handle(String original) {
            return DesensitizationUtil.realName(original);
        }
    }

}
